Skip to content

Conversation

@segiddins
Copy link
Contributor

This adds an optional buffer argument to the Cipher#final method, matching the behavior of Cipher#update. When a buffer is provided, the output is written to it and the same buffer object is returned. Otherwise, a new string is created and returned.

The implementation follows the same pattern as update:

  • Accepts an optional string buffer parameter
  • Reuses the buffer if provided, creating a new string if not
  • Automatically resizes the buffer as needed
  • Forces ASCII-8BIT encoding for binary cipher output
  • Raises FrozenError if the buffer is frozen

This adds an optional buffer argument to the Cipher#final method,
matching the behavior of Cipher#update. When a buffer is provided,
the output is written to it and the same buffer object is returned.
Otherwise, a new string is created and returned.

The implementation follows the same pattern as update:
- Accepts an optional string buffer parameter
- Reuses the buffer if provided, creating a new string if not
- Automatically resizes the buffer as needed
- Forces ASCII-8BIT encoding for binary cipher output
- Raises FrozenError if the buffer is frozen
@rhenium
Copy link
Member

rhenium commented Dec 26, 2025

Why is this needed or desirable?

@segiddins
Copy link
Contributor Author

It allows using a cipher to only require a single string allocation, by reusing the buffer passed to update, as opposed to allocating a second string inside final only to then append it to the buffer caller-side

@rhenium
Copy link
Member

rhenium commented Dec 27, 2025

Have you measured the performance impact?

#final only allocates a small, usually RString-embedded string. My gut feeling is that avoiding this allocation isn't worth adding extra complexity to OpenSSL::Cipher, which is already fairly complicated.

@segiddins
Copy link
Contributor Author

segiddins commented Jan 28, 2026

On one request I was profiling, we were allocating 140784 objects there just for "\u0000", which is IMO just unnecessary GC churn when the allocation is completely avoidable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants